package com.jiangxjsy.crm.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONObject;
import com.jiangxjsy.core.common.CrmModule;
import com.jiangxjsy.core.constant.BasicConstant;
import com.jiangxjsy.core.constant.CrmCacheKey;
import com.jiangxjsy.core.constant.RedisCacheConstant;
import com.jiangxjsy.core.exception.AuthorizationException;
import com.jiangxjsy.core.jwt.JwtCore;
import com.jiangxjsy.core.page.BasePage;
import com.jiangxjsy.core.redis.Redis;
import com.jiangxjsy.core.wrap.ResultCode;
import com.jiangxjsy.crm.client.AdminClient;
import com.jiangxjsy.crm.client.ExamineClient;
import com.jiangxjsy.crm.mapper.CrmBackLogDealMapper;
import com.jiangxjsy.crm.property.JwtProperty;
import com.jiangxjsy.crm.service.*;
import com.jiangxjsy.crm.support.CrmBackLogDealSupport;
import com.jiangxjsy.model.admin.entity.AdminConfig;
import com.jiangxjsy.model.core.entity.UserInfo;
import com.jiangxjsy.model.core.entity.UserMeta;
import com.jiangxjsy.model.crm.bo.CrmBackLogBO;
import com.jiangxjsy.model.crm.bo.CrmSearchBO;
import com.jiangxjsy.model.crm.entity.CrmBackLogDeal;
import com.jiangxjsy.model.crm.entity.CrmCustomerPool;
import com.jiangxjsy.model.crm.entity.CrmCustomerPoolRule;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * wukong-crm-master
 * 蒋胜宇
 * 2025/6/16 14:15
 */

@Service
public class CrmBackLogDealServiceImpl implements CrmBackLogDealService {
    @Resource
    private CrmBackLogDealMapper crmBackLogDealMapper;

    @Resource
    private CrmCustomerPoolService crmCustomerPoolService;

    @Resource
    private CrmCustomerPoolRuleService crmCustomerPoolRuleService;

    @Resource
    private CrmContractService crmContractService;

    @Resource
    private CrmReceivablesService crmReceivablesService;

    @Resource
    private CrmInvoiceService crmInvoiceService;

    @Resource
    private CrmLeadsService crmLeadsService;

    @Resource
    private AdminClient adminClient;

    @Resource
    private ExamineClient examineClient;

    @Resource
    private CrmBackLogDealSupport crmBackLogDealSupport;

    @Resource
    private JwtProperty jwtProperty;

    @Resource
    private Redis redis;

    /**
     * 待办事项数量
     *
     * @param request 请求
     * @param response 响应
     * @return 待办事项数量
     */
    @Override
    public JSONObject num(HttpServletRequest request, HttpServletResponse response) {
        String token = request.getHeader(BasicConstant.TOKEN_NAME);
        UserMeta userMeta;
        try {
            userMeta = new JwtCore<>(UserMeta.class).analyzeToken(token, jwtProperty.getPublicKey());
        } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException | InstantiationException e) {
            throw new AuthorizationException(ResultCode.AuthorizationResultCode.AUTHORIZATION_LOGIN_ERR);
        }
        Long userId = userMeta.getUserId();

        JSONObject kv = (JSONObject) redis.get(CrmCacheKey.CRM_BACKLOG_NUM_CACHE_KEY + userId.toString());
        if (kv != null) {
            return kv;
        } else {
            kv = new JSONObject();
        }

        UserInfo userInfo = redis.get(UserInfo.class, token);
        List<String> authList = userInfo.getAuthoritiesUrlList();
        authList.add("crm:customer:index");
        authList.add("crm:leads:index");
        authList.add("crm:contract:index");
        authList.add("crm:receivables:index");
        authList.add("crm:receivables:index");
        authList.add("crm:invoice:index");
        Map<String, Object> paras = new HashMap<>();
        paras.put("userId", userId);

        if (authList.contains("crm:customer:index")) {
            Integer todayLeads = crmBackLogDealMapper.todayLeadsNum(paras);
            Integer todayCustomer = crmBackLogDealMapper.todayCustomerNum(paras);
            Integer todayBusiness = crmBackLogDealMapper.todayBusinessNum(paras);
            Integer followCustomer = crmBackLogDealMapper.followCustomerNum(paras);
            kv.put("todayLeads", todayLeads);
            kv.put("todayCustomer", todayCustomer);
            kv.put("todayBusiness", todayBusiness);
            kv.put("followCustomer", followCustomer);
            List<CrmCustomerPool> poolList = crmCustomerPoolService.queryEnabledPools();
            Set<Integer> customerIdSet = new HashSet<>();

            poolList.forEach(pool -> {
                List<JSONObject> recordList = new ArrayList<>();
                List<CrmCustomerPoolRule> ruleList = crmCustomerPoolRuleService.queryRulesByPoolId(pool.getPoolId());
                for (CrmCustomerPoolRule rule : ruleList) {
                    Map<String, Object> record = BeanUtil.beanToMap(rule);
                    record.put("remindDay", pool.getRemindDay());
                    record.put("ids", Collections.singletonList(userId));
                    if (rule.getType().equals(1L)) {
                        recordList.addAll(crmBackLogDealMapper.putInPoolByRecord(record));
                    } else if (rule.getType().equals(2L)) {
                        recordList.addAll(crmBackLogDealMapper.putInPoolByBusiness(record));
                    } else if (rule.getType().equals(3L)) {
                        Long startDay = rule.getLimitDay() - pool.getRemindDay();
                        record.put("startDay", startDay);
                        recordList.addAll(crmBackLogDealMapper.putInPoolByDealStatus(record));
                    }
                }
                List<Integer> customerIdList = recordList.stream().map(record -> record.getInteger("customerId")).collect(Collectors.toList());
                List<Integer> dealIdList = crmBackLogDealMapper.selectDealTypeIdsByUserId(4, 9, userId);
                customerIdList.removeAll(dealIdList);
                customerIdSet.addAll(customerIdList);
            });
            if (!poolList.isEmpty()) {
                kv.put("putInPoolRemind", customerIdSet.size());
            }
        }

        if (authList.contains("crm:leads:index")) {
            Integer followLeads = crmBackLogDealMapper.followLeadsNum(paras);
            kv.put("followLeads", followLeads);
        }

        if (authList.contains("crm:contract:index")) {
            AdminConfig adminConfig = adminClient.queryFirstConfigByName("expiringContractDays").getData();
            if (1 == adminConfig.getStatus()) {
                paras.put("remindDay", adminConfig.getValue());
                Integer endContract = crmBackLogDealMapper.endContractNum(paras);
                kv.put("endContract", endContract);
            }
            List<Integer> ids = examineClient.queryCrmExamineIdList(1, 1).getData();
            Integer checkContract = null;
            if (CollUtil.isNotEmpty(ids)) {
                List<Integer> dealIdList = crmBackLogDealMapper.selectDealTypeIdsByUserId(5, CrmModule.CONTRACT.getType(), userId);
                ids.removeAll(dealIdList);
                if (!ids.isEmpty()) {
                    checkContract = crmContractService.countContractsByIdsAndCheckStatus(ids);
                }
            }
            if (checkContract == null) {
                checkContract = 0;
            }
            kv.put("checkContract", checkContract);

            AdminConfig returnVisitRemindConfig = adminClient.queryFirstConfigByName("returnVisitRemindConfig").getData();
            if (1 == returnVisitRemindConfig.getStatus()) {
                paras.put("remindDay", returnVisitRemindConfig.getValue());
                Integer returnVisitRemind = crmBackLogDealMapper.returnVisitRemindNum(paras);
                kv.put("returnVisitRemind", returnVisitRemind);
            }
        }

        if (authList.contains("crm:receivables:index")) {
            Integer remindReceivablesPlan = crmBackLogDealMapper.remindReceivablesPlanNum(paras);
            List<Integer> ids = examineClient.queryCrmExamineIdList(2, 1).getData();
            Integer checkReceivables = null;
            if (CollUtil.isNotEmpty(ids)) {
                List<Integer> dealIdList = crmBackLogDealMapper.selectDealTypeIdsByUserId(6, CrmModule.RECEIVABLES.getType(), userId);
                ids.removeAll(dealIdList);
                if (!ids.isEmpty()) {
                    checkReceivables = crmReceivablesService.countReceivablesByIdsAndCheckStatus(ids);
                }
            }
            if (checkReceivables == null) {
                checkReceivables = 0;
            }
            kv.put("checkReceivables", checkReceivables);
            kv.put("remindReceivablesPlan", remindReceivablesPlan);
        }

        if (authList.contains("crm:invoice:index")) {
            List<Integer> ids = examineClient.queryCrmExamineIdList(3, 1).getData();
            Integer checkInvoice = null;
            if (CollUtil.isNotEmpty(ids)) {
                List<Integer> dealIdList = crmBackLogDealMapper.selectDealTypeIdsByUserId(10, CrmModule.INVOICE.getType(), userId);
                ids.removeAll(dealIdList);
                if(!ids.isEmpty()){
                    checkInvoice = crmInvoiceService.countInvoiceByIdsAndCheckStatus(ids);
                }
            }
            if (checkInvoice == null) {
                checkInvoice = 0;
            }
            kv.put("checkInvoice", checkInvoice);
        }

        redis.setEx(CrmCacheKey.CRM_BACKLOG_NUM_CACHE_KEY + userId, kv, RedisCacheConstant.MAX_CACHE_TIME, TimeUnit.MINUTES);

        return kv;
    }

    /**
     * 今日需联系线索
     *
     * @param crmBackLogBO 请求
     * @param request 请求
     * @param response 响应
     * @return 今日需联系线索
     */
    @Override
    public BasePage<Map<String, Object>> todayLeads(CrmBackLogBO crmBackLogBO, HttpServletRequest request, HttpServletResponse response) {
        String token = request.getHeader(BasicConstant.TOKEN_NAME);
        UserMeta userMeta;
        try {
            userMeta = new JwtCore<>(UserMeta.class).analyzeToken(token, jwtProperty.getPublicKey());
        } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException | InstantiationException e) {
            throw new AuthorizationException(ResultCode.AuthorizationResultCode.AUTHORIZATION_LOGIN_ERR);
        }
        Long userId = userMeta.getUserId();

        crmBackLogDealSupport.setCrmBackLogBO(crmBackLogBO, CrmModule.LEADS, userId);
        CrmSearchBO searchBO = new CrmSearchBO();
        searchBO.setLabel(CrmModule.LEADS.getType());
        searchBO.setPage(crmBackLogBO.getPage());
        searchBO.setLimit(crmBackLogBO.getLimit());
        searchBO.setSearchList(crmBackLogBO.getData());
        BasePage<Map<String, Object>> basePage = crmLeadsService.queryPageList(searchBO);
        Integer overtimeNum = crmBackLogDealMapper.todayOvertimeNum(crmBackLogDealSupport.getOvertimeQueryData(CrmModule.LEADS, userId));
        basePage.setExtraData(Collections.singletonMap("overtime",overtimeNum));
        return basePage;
    }

    /**
     * 查询类型ID
     *
     * @param model 模块
     * @param crmType 模块类型
     * @param userId 用户ID
     * @return 类型ID
     */
    @Override
    public List<String> queryTypeId(Integer model, Integer crmType, Long userId) {
        List<CrmBackLogDeal> list = crmBackLogDealMapper.selectTypeId(model, crmType, userId);
        return list.stream().map(log -> log.getTypeId().toString()).collect(Collectors.toList());
    }
}
